﻿using System.ComponentModel;
using System.Reflection;
using System.Runtime.Serialization;
using System.Linq.Expressions;
using System;
using System.Text.RegularExpressions;

namespace SmartMD.DataModel
{
    /// <summary>
    /// 实体基类，所有数据实体都是从该类继承的
    /// </summary>
    public class EntityBase : INotifyPropertyChanged
    {
        private string _guid;
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        protected virtual void OnPropertyChanged(Expression<Func<object>> expression)
        {
            if (expression != null)
            {
                if (expression.NodeType == ExpressionType.Lambda)
                {
                    MemberExpression body = null;
                    if (expression.Body is UnaryExpression)
                    {
                        var ue = expression.Body as UnaryExpression;
                        body = ue.Operand as MemberExpression;
                    }
                    else
                    {
                        body = expression.Body as MemberExpression;
                    }
                    if (body != null)
                    {
                        string propertyName = body.Member.Name;
                        OnPropertyChanged(propertyName);
                    }
                }
            }
        }

        [IgnoreDataMember]
        public string Guid
        {
            get
            {
                if (string.IsNullOrEmpty(_guid))
                    _guid = System.Guid.NewGuid().ToString();
                return _guid;
            }
        }

        public void Clone(EntityBase source)
        {
            if (source == null) return;

            if (this.GetType().Equals(source.GetType()) || source.GetType().IsSubclassOf(this.GetType()))
                foreach (var info in this.GetType().GetProperties())
                {
                    if (info.CanWrite && (info.PropertyType.IsPrimitive || info.PropertyType.Equals(typeof(string))))
                        info.SetValue(this, info.GetValue(source, null), null);
                }
        }

        public virtual bool Check(out string message)
        {
            var type = this.GetType();
            message = null;
            foreach (var propertyInfo in type.GetProperties())
            {
                message = CheckValueAttribute.Check(this, propertyInfo);
                if (!string.IsNullOrEmpty(message))
                {
                    return false;
                }
            }
            return true;
        }

        public virtual void setValue(string key, Object value)
        {
        }
    }

    public class CheckValueAttribute : Attribute
    {
        public CheckValueAttribute(string message)
        {
            this.Message = message;
        }

        public string Regular { get; set; }
        public string Message { get; set; }

        public static string Check(object obj, PropertyInfo info)
        {
            var value = info.GetValue(obj, null);
            var attrs = info.GetCustomAttributes(typeof(CheckValueAttribute), false);
            if (attrs.Length == 0) return null;
            var attr = (CheckValueAttribute)attrs[0];
            if (value == null) return attr.Message;
            //没有正则表达式时判断是否为空
            if (string.IsNullOrEmpty(attr.Regular))
            {
                return string.IsNullOrEmpty(value.ToString()) ? attr.Message : null;
            }

            var regular = new Regex(attr.Regular, RegexOptions.IgnoreCase);
            //正则表达式判断条件是否成立
            if (regular.IsMatch(value.ToString()))
            {
                return null;
            }
            return attr.Message;
        }
        /**
         * 对实体属性设值
         * 
         * */
       
    }
}
